4.1 Виджеты. Stateless и Stateful
3 из 3 шагов пройдено

 Виджеты. Stateless и Stateful

➡️Скачать презентацию. Flutter Stateful
➡️Ссылка на репозиторий с кодом этого урока

Подготовка

В папку stateful_widgets добавим новый файл с названием s2_stateful_widget.dart

Сделаем отдельные виджеты для каждого компонента карточки:

для title  TitleWidget
для subtitle  SubtitleWidget
для trailing  LikeButton

Управление состоянием из родительского виджета

Файл s2_stateful_widget.dart

import 'package:flutter/material.dart';

class TrackCard extends StatelessWidget {  
  const TrackCard({super.key});  
  
  @override  
  Widget build(BuildContext context) {  
    return Card(  
      color: Colors.white,  
      child: ListTile(  
        leading: Image.asset("assets/images/pro.webp"),  
        title: const TitleWidget(text: "Stateless"),  
        subtitle: const SubtitleWidget(text: "Flutter vibes"),  
        trailing: LikeButton(text: "Like"),  // Передаем параметр для Stateful
      ),  
    );  
  }  
}

Файл s2_stateful_widget.dart 

class TitleWidget extends StatelessWidget {  
  final String text;  
  const TitleWidget({super.key, this.text = ""});  
  
  @override  
  Widget build(BuildContext context) {  
    return Text(  
      text,  
      style: TextStyle(  
        fontWeight: FontWeight.bold,  
      ),  
    );  
  }  
}

Файл s2_stateful_widget.dart 

class SubtitleWidget extends StatelessWidget {  
  final String text;  
  
  const SubtitleWidget({super.key, this.text = ""});  
  @override  
  Widget build(BuildContext context) {  
    return Text(text.toUpperCase());  
  }  
}

Сделаем LikeButton как StatefulWidget, чтобы он управлял только сменой иконки

widget и state

  • В данном случае StatefulWidget принимает параметр text
  • Чтобы получить доступ к этому параметру внутри State, нужно обращаться к нему через объект widget.text

Файл s2_stateful_widget.dart  

class LikeButton extends StatefulWidget {  
  final String text;  
  const LikeButton({super.key, this.text = ""});  
  
  @override  
  State<LikeButton> createState() => _LikeButtonState();  
}  
  
class _LikeButtonState extends State<LikeButton> {  
  bool isFavorite = false;  
  
  @override  
  Widget build(BuildContext context) {  
  
    return Column(  
      mainAxisAlignment: MainAxisAlignment.center,  
      crossAxisAlignment: CrossAxisAlignment.center,  
      children: [  
        Expanded(  
          child: IconButton(  
            onPressed: () {  
              setState(() {  
                isFavorite = !isFavorite;  
              });  
            },  
            icon: isFavorite  
                ? const Icon(Icons.favorite, color: Colors.red)  
                : const Icon(Icons.favorite_border),  
          ),  
        ),  
        Text(widget.text),  // Чтобы получить доступ к свойствам виджета
      ],  
    );  
  }  
}

Передача колбэк-функции

  • Сделаем виджет TrackCard как StatefulWidget и добавим ему хранение и управление состоянием счётчика лайков.
  • Но вызывать запрос на изменение состояния будет виджет потомок LikeButton!
  • Для этого нужно в виджет LikeButton передать как параметр целую функцию!
  • Такой подход называется передача колбэка или передача обратной функции.

Файл s2_stateful_widget.dart 

class TrackCard extends StatefulWidget {  
  const TrackCard({super.key});  
  
  @override  
  State<TrackCard> createState() => _TrackCardState();  
}  
  
class _TrackCardState extends State<TrackCard> {  
  int counter = 0;  // Состояние хранение счётчика лайков

  // Функция для изменения состояния
  void _incCount() => setState(() {  
        counter++;  
      });  
  
  @override  
  Widget build(BuildContext context) {  
    return Card(  
      color: Colors.white,  
      child: ListTile(  
        leading: Image.asset("assets/images/pro.webp"),  
        title: const TitleWidget(text: "Stateless"),  
        subtitle: const SubtitleWidget(text: "Flutter vibes"),  
        trailing: LikeButton(  
          text: "Like $counter", // Передаем значение состояния  
          incCount: _incCount,  // Передаем в параметр целую функцию
        ),  
      ),  
    );  
  }  
}

⭕Важно! Когда передаём функцию-колбэк как параметр, пишем только название функции!
⭕Без круглых скобок в конце!

trailing: LikeButton(  
  text: "Like $counter", 
  incCount: _incCount, // Передаем в параметр целую функцию
),  

Файл s2_stateful_widget.dart 

class LikeButton extends StatefulWidget {  
  final String text;  
  final Function incCount;  
  
  const LikeButton({super.key, this.text = "", required this.incCount});
  
  @override  
  State<LikeButton> createState() => _LikeButtonState();  
}  
  
class _LikeButtonState extends State<LikeButton> {  
  bool isFavorite = false;  
  
  @override  
  Widget build(BuildContext context) {  
    return Column(  
      mainAxisAlignment: MainAxisAlignment.center,  
      crossAxisAlignment: CrossAxisAlignment.center,  
      children: [  
        Expanded(  
          child: IconButton(  
            onPressed: () {  
              isFavorite = !isFavorite; 

			  // Вызываем функцию-колбэк из виджета TrackCard
              widget.incCount();   
            },  
            icon: isFavorite  
                ? const Icon(Icons.favorite, color: Colors.red)  
                : const Icon(Icons.favorite_border),  
          ),  
        ),  
        Text(widget.text),  
      ],  
    );  
  }  
}

Будьте вежливы и соблюдайте наши принципы сообщества. Пожалуйста, не оставляйте решения и подсказки в комментариях, для этого есть отдельный форум.
Оставить комментарий
Нет обсуждений. Начните первое.